package com.salton123.voice.recorder;


import android.annotation.SuppressLint;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.salton123.voice.recorder.UniteUtil.SUFFIX_AMR;

public class AudioRecorderHelper implements IAudioRecorder {
    private static AudioRecorderHelper mInstance;

    public static AudioRecorderHelper getInstance() {
        if (mInstance == null) {
            synchronized (AudioRecorderHelper.class) {
                if (mInstance == null) {
                    mInstance = new AudioRecorderHelper();
                }
            }
        }
        return mInstance;
    }

    private static final String TAG = "AudioRecorderHelper";

    private List<String> toUniteFileList = new ArrayList<>();
    private long mRecordTimePreview;    //直到上次为止一共录制了多少毫秒
    private long mRecordTimeTotal;     //到目前为止一共录制了多少毫秒
    public MediaRecorder mMediaRecorder;
    public OnRecordStateChangeListener mListener;
    public String mDataSource = ""; //当前录制的音频文件
    public String mToSaveDir = "";  //当前保存这次录制的所有分段音频路径
    private int mState = 0;
    private static final int TYPE_UPDATE_PROGRESS_MESSAGE = 0x101;
    private static final long UPDATE_PROGRESS_DEFAULT_INTERVAL = 100;

    @SuppressLint("HandlerLeak")
    private Handler mMessageHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case TYPE_UPDATE_PROGRESS_MESSAGE:
                    onUpdateProgress();
                    break;
            }
        }
    };

    /**
     * 发送更新播放进度的消息
     */
    private void onUpdateProgress() {
        if (mState == RecorderState.STATE_RECORDING) {
            if (mListener != null) {
                mListener.onProgress(mRecordTimeTotal, mDataSource);
            }
            mMessageHandler.sendEmptyMessageDelayed(TYPE_UPDATE_PROGRESS_MESSAGE, UPDATE_PROGRESS_DEFAULT_INTERVAL);
        } else {
            mMessageHandler.removeMessages(TYPE_UPDATE_PROGRESS_MESSAGE);
        }
    }

    public void setOnRecordStateChangeListener(OnRecordStateChangeListener recordStateChangeListener) {
        this.mListener = recordStateChangeListener;
    }

    @Override
    public IAudioRecorder path(String toSaveDir) {
        if (TextUtils.isEmpty(toSaveDir)) {
            if (mListener != null) {
                mListener.onError("toSaveDir == null", "");
                mState = RecorderState.STATE_ERROR;
            }
        }
        if (!FileUtil.isFolderExist(toSaveDir)) {
            if (!FileUtil.makeDirs(toSaveDir)) {
                if (mListener != null) {
                    mListener.onError("toSaveDir makeDirs error", toSaveDir);
                    mState = RecorderState.STATE_ERROR;
                }
            }
        }
        this.mToSaveDir = toSaveDir;
        mState = RecorderState.STATE_IDLE;
        return this;
    }

    @Override
    public IAudioRecorder start() {
        try {
            Log.i(TAG, "start record");
            if (mState != RecorderState.STATE_RECORDING ||
                    mState != RecorderState.STATE_ERROR) {
                mState = RecorderState.STATE_IDLE;
                String tempRecordFile = createTempFile(mToSaveDir, SUFFIX_AMR);
                mDataSource = tempRecordFile;
                toUniteFileList.add(tempRecordFile);
                mMediaRecorder = new MediaRecorder();
                // 设置音频录入源
                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                // 设置录制音频的输出格式
                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
                // 设置音频的编码格式
                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                // 设置录制音频文件输出文件路径
                mMediaRecorder.setOutputFile(tempRecordFile);
                mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                    @Override
                    public void onError(MediaRecorder mr, int what, int extra) {
                        if (mListener != null) {
                            mListener.onError("error,what:" + what + ",extra:" + extra, mDataSource);
                            mState = RecorderState.STATE_ERROR;
                            Log.i(TAG, "error,what:" + what + ",extra:" + extra);
                        }
                    }
                });
                mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
                    @Override
                    public void onInfo(MediaRecorder mr, int what, int extra) {

                    }
                });
                if (mListener != null) {
                    mListener.onPreparing(mDataSource);
                }
                mState = RecorderState.STATE_PREPARED;
                mMediaRecorder.prepare();
                if (mListener != null) {
                    mListener.onStart(mDataSource);
                }
                mState = RecorderState.STATE_RECORDING;
                onUpdateProgress();
                mMediaRecorder.start();
            } else {
                Log.i(TAG, "start record error ,state error:" + mState);
            }
        } catch (IOException e) {
            if (mListener != null) {
                mListener.onError("ex:" + e.getLocalizedMessage(), mDataSource);
            }
        }
        return this;
    }

    @Override
    public IAudioRecorder stop() {
        Log.i(TAG, "[stop]");
        if (mState == RecorderState.STATE_RECORDING) {
            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
            }
            if (mListener != null) {
                mListener.onStop(mDataSource);
            }
            mState = RecorderState.STATE_STOP;
            Log.i(TAG, "[stop] success");
        }
        return this;
    }

    @Override
    public IAudioRecorder release() {
        Log.i(TAG, "[release]");
        if (mState != RecorderState.STATE_STOP) {
            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
            }
            for (String item : toUniteFileList) {
                new File(item).delete();
            }
            toUniteFileList.clear();
            Log.i(TAG, "[release] success");
        }
        mState = RecorderState.STATE_RELEASE;
        return this;
    }

    public boolean isRecording() {
        return mState == RecorderState.STATE_RECORDING;
    }

    public File getUniteAudioFile() {
        File file = UniteUtil.getUniteAmrAudioFile(toUniteFileList, mToSaveDir);
        if (file != null) {
            Log.i(TAG, "[getUniteAudioFile] " + file.getAbsolutePath());
        }
        return file;
    }

    public String createTempFile(String toSaveDir, String suffix) {
        long timeMills = System.currentTimeMillis();
        if (!toSaveDir.endsWith(File.separator)) {
            toSaveDir = toSaveDir + File.separator;
        }
        String tempFile = toSaveDir + timeMills + suffix;
        FileUtil.makeDirs(tempFile);
        Log.i(TAG, "[createTempFile] " + tempFile);
        return tempFile;
    }

    public interface OnRecordStateChangeListener {
        void onPreparing(String dataSource);

        void onStart(String dataSource);

        void onStop(String dataSource);

        void onError(String msg, String dataSource);

        void onProgress(long totalRecordTime, String dataSource);

    }
}
